package cn.edu.neu.softlab633.influencemaximization.sy.CELF_Algorithm;

import cn.edu.neu.softlab633.influencemaximization.sy.M_TLTGreedy.M_TLTGreedy;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.CELF.CELFQueue;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.CELF.CELFQueueEle;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.Graph;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.MarginGain;
import cn.edu.neu.softlab633.influencemaximization.sy.model.lt.LinearThresholdModel;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;

/**
 * Created by Jason on 2017/5/24.
 */
public class CELF_Algorithm_useCELFQueue {
    public static int celfAlgorithm(double threshold, Double[] query, int k, Graph graph) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("data/result_CELF_WZ_" + threshold + "_" + k + ".txt"));
        long start = System.currentTimeMillis();
        CELFQueue celfQueue = new CELFQueue();
        celfQueue.initCELFQueue(threshold, query, graph);
        MarginGain seed_gain = new MarginGain(0, new HashSet<Integer>());
        int influence_current = 0;
        ArrayList<Integer> seed = new ArrayList<>();
        while (seed.size() < k) {
            if (seed.size() % 10 == 0) {
                long end = System.currentTimeMillis();
                System.out.println("CELF:    k = " + seed.size());
                bw.write("CELF:    k = " + seed.size());
                bw.newLine();
                bw.write("    influence spread: " + influence_current);
                bw.newLine();
                bw.write("    running time: " + (end - start) + "ms");
                bw.newLine();
                System.out.println("    influence spread: " + influence_current);
                System.out.println("    running time: " + (end - start) + "ms");
            }
            CELFQueueEle peek = celfQueue.peek();
            MarginGain gain_current = peek.getGain();
            int k_current = seed.size() + 1;
            while (peek.getRound() != k_current) {
//                seed_gain.getMarginGainNode().add(peek.getId());
                MarginGain tmp = LinearThresholdModel.influencePropagation(threshold, query, M_TLTGreedy.getCurrentSeed(seed, peek.getId()), graph);
//                seed_gain.getMarginGainNode().remove(peek.getId());
                gain_current = tmp.sub(seed_gain);
                celfQueue.add(new CELFQueueEle(peek.getId(), gain_current, k_current));
                peek = celfQueue.peek();
            }
            if (peek.getGain().getMarginGainNum() <= 0) {
                System.out.println("影响力为0");
                break;
            }
            seed.add(peek.getId());
            seed_gain = seed_gain.add(peek.getGain());
            influence_current += peek.getGain().getMarginGainNum();
        }
        long end = System.currentTimeMillis();
        System.out.println("CELF:    k = " + seed.size());
        bw.write("CELF:    k = " + seed.size());
        bw.newLine();
        bw.write("    influence spread: " + influence_current);
        bw.newLine();
        bw.write("    running time: " + (end - start) + "ms");
        bw.newLine();
        System.out.println("    influence spread: " + influence_current);
        System.out.println("    running time: " + (end - start) + "ms");
        System.out.println("    影响力传播范围：" + influence_current);
        System.out.print("    种子集合为：  ");
        for (int i = 0; i < seed.size(); i++) {
            Integer integer = seed.get(i);
            System.out.print(integer + "  ");
        }
        bw.close();
        return influence_current;
    }
}
